#include<linux/module.h>
#include<linux/sched.h>
#include<linux/list.h>
#include<linux/kthread.h>
MODULE_LICENSE("GPl");
int my_function(void *argc)
{
	printk("in the kernel thread function!\n");
	printk("the current pid is:%d\n",current->pid);
	printk("out the kernel thread function!\n");
	return 0;
}
static int __init prepare_to_wait_exclusive_init(void)
{
	struct task_struct *result,*result1,*result2,*result3;
	int wait_queue_num=0;
	wait_queue_head_t head;
	wait_queue_t data,data1,data2,data3,*curr,*next;
	printk("into prepare_to_wait_exclusive_init.\n");

	result=kthread_create_on_node(my_function,NULL,-1,"prepare_to_wait_exclusive");
	result1=kthread_create_on_node(my_function,NULL,-1,"prepare_to_wait_exclusive1");
	result2=kthread_create_on_node(my_function,NULL,-1,"prepare_to_wait_exclusive2");
	result3=kthread_create_on_node(my_function,NULL,-1,"prepare_to_wait_exclusive3");
	wake_up_process(result);
	wake_up_process(result1);
	wake_up_process(result2);
	wake_up_process(result3);

	init_waitqueue_head(&head);
	init_waitqueue_entry(&data,result);
	data.task_list.next=&data.task_list;
	printk("the state of the current thread is:%ld\n",current->state);

	prepare_to_wait(&head,&data,130);
	printk("the state of the current thread is:%ld\n",current->state);

	init_waitqueue_entry(&data1,result1);
	data1.task_list.next=&data1.task_list;
	prepare_to_wait(&head,&data1,2);
	printk("the state of the current thread is:%ld\n",current->state);


	init_waitqueue_entry(&data2,result2);
	prepare_to_wait(&head,&data2,2);
	printk("the state of the current thread is:%ld\n",current->state);

	init_waitqueue_entry(&data3,result3);
	prepare_to_wait(&head,&data3,2);
	printk("the state of the current thread is:%ld\n",current->state);

	list_for_each_entry_safe(curr,next,&(head.task_list),task_list)
	{
		wait_queue_num++;	
		printk("the flag value of the current data of the waitqueue is:%d\n",curr->flags);
		printk("the pid value of the current data of the waitqueue is:%d\n",
				((struct task_struct*)(curr->private))->pid);
	}
	printk("the value of the wait_queue_num is:%d\n",wait_queue_num);
	data2.task_list.next=&data2.task_list;
	data3.task_list.next=&data3.task_list;
	prepare_to_wait(&head,&data2,1);
	prepare_to_wait_exclusive(&head,&data3,0);
	wait_queue_num=0;

	list_for_each_entry_safe(curr,next,&(head.task_list),task_list)
	{
		wait_queue_num++;	
		printk("the flag value of the current data of the waitqueue is:%d\n",curr->flags);

		printk("the pid value of the current data of the waitqueue is:%d\n",
				((struct task_struct*)(curr->private))->pid);
	}
	printk("the value of the wait_queue_num is:%d\n",wait_queue_num);

	printk("pid of new thread is:%d,%d,%d,%d\n",result->pid,result1->pid,result2->pid,result3->pid);
	printk("the current pid is:%d\n",current->pid);
	printk("out prepare_to_wait_init.\n");
	return 0;
}
static void __exit prepare_to_wait_exclusive_exit(void)
{
	printk("Goodbye prepare_to_wait\n");
}
module_init(prepare_to_wait_exclusive_init);
module_exit(prepare_to_wait_exclusive_exit);
